﻿using Bettzueche.RLLibrary.Types;

namespace Bettzueche.RLLibrary.Functions {
    /// <summary>
    /// Q-Value function (auch action-value function genannt), die einem Zustands-Aktions-Paar einen Wert zuweist.<br />
    /// Q : SxA --> Double
    /// </summary>
    /// <para>
    /// Der Q-Wert eines Zustands s ist die zu erwartende, aufsummierte Belohnung, die ausgehend von s unter Auswahl 
    /// einer bestimmten Aktion a und der anschließenden Verfolgung einer Strategie π erreicht werden kann. Der Q-Wert
    /// ist ein Gütemaß einer Aktion in einem Zustand und seine Funktion wird üblicherweise geschätzt bzw. erlernt.
    /// </para>
    public interface IStateValueFunction {

        /// <summary>
        /// Gibt oder setzt den Wert (Q-Value)
        /// </summary>
        /// <param name="state">Zustand</param>
        /// <param name="action">Aktion</param>
        /// <returns>Q(s,a)</returns>
        double this[IState state, IAction action] { get; /*set;*/ }

        ///// <summary>
        ///// Gets the Values.
        ///// </summary>
        ///// <value>
        ///// The values.
        ///// </value>
        //Matrix Values { get; set; }

        /// <summary>
        /// Gets all values of the specified state.
        /// <para>(Optional)</para>
        /// </summary>
        /// <param name="state">The state.</param>
        /// <returns>All Function values of the specified state.</returns>
        double[] GetEstimates(IState state);

    }



    /// <summary>
    /// Generische Q-Value function (auch action-value function genannt), die einem Zustands-Aktions-Paar einen Wert zuweist.<br />
    /// Q : SxA --> Double
    /// </summary>
    /// <para>
    /// Der Q-Wert eines Zustands s ist die zu erwartende, aufsummierte Belohnung, die ausgehend von s unter Auswahl 
    /// einer bestimmten Aktion a und der anschließenden Verfolgung einer Strategie π erreicht werden kann. Der Q-Wert
    /// ist ein Gütemaß einer Aktion in einem Zustand und seine Funktion wird üblicherweise geschätzt bzw. erlernt.
    /// </para>
    /// <typeparam name="S">Type of IState</typeparam>
    /// <typeparam name="A">Type of IAction</typeparam>
    public interface IStateValueFunction<S, A> : IStateValueFunction
        where S : IState
        where A : IAction
    {
        /// <summary>
        /// Gibt oder setzt den Wert (Q-Value)
        /// </summary>
        /// <param name="state">Zustand</param>
        /// <param name="action">Aktion</param>
        /// <returns>Q(s,a)</returns>
        double this[S state, A action] { get; set; }

        /// <summary>
        /// Gets all values of the specified state.
        /// <para>(Optional)</para>
        /// </summary>
        /// <param name="state">The state.</param>
        /// <returns>All Function values of the specified state.</returns>
        double[] GetEstimates(S state);

        /// <summary>
        /// Adds the specified eligibility values, each one multiplied by <c>factor</c>, to this values.<para>
        /// Optional conveniance method for updating the Q-Function: W = W + (α·δ)·E or
        /// forall (s,a): Q(s,a) = Q(s,a) + factor * E(a,s)
        /// </para>
        /// </summary>
        /// <param name="eFunction">The e function.</param>
        /// <param name="factor">The factor.</param>
        void Add(IEligibilityFunction<A, S> eFunction, double factor);

        /// <summary>
        /// Adds the specified eligibility values to this values.<para>
        /// Optional conveniance method for updating the Q-Function
        /// </para>
        /// </summary>
        /// <param name="eFunction">The e function.</param>
        void Add(IEligibilityFunction<A, S> eFunction);

        /// <summary>
        /// Adds the specified matrix values to this values.<para>
        /// Optional conveniance method for updating the Q-Function
        /// </para>
        /// </summary>
        /// <param name="m">The matrix.</param>
        void Add(Matrix m);
    }
}
